﻿using Adaptive.Agrona.Concurrent;
using Adaptive.Agrona.Concurrent.RingBuffer;
using Microsoft.Extensions.Logging;
using Unity.Commons.Client.Buffer;
using Unity.Commons.Client.Offline;
using Unity.Connections;
using Unity.Credentials;
using Unity.Logger;

namespace Unity.Debug
{
    public class ConsoleUnityClientFactory
    {
        private static readonly ILogger Logger =
            UnityLogger.ConsoleLoggerFactory.CreateLogger(nameof(ConsoleUnityClientFactory));

        private static IUnityConnectionFactory _connectionFactory;
        
        private static IUnityProducer GetUnityProducer(IUnityCredentials credentials)
        {
            if (_connectionFactory == null)
            {
                _connectionFactory = new ConsoleUnityProducerFactory();
            }
            return new ConsoleUnityProducer(credentials);
        }

        public static ConsoleUnityClient MakeUnityClient(IMessageQueueCredentials topicCredentials, IUnityCredentials credentials,
            IOfflineHandler offlineHandler)
        {
            if (topicCredentials == null)
            {
                throw new System.ArgumentNullException(nameof(credentials));
            }
            
            if (offlineHandler == null)
            {
                throw new System.ArgumentNullException(nameof(offlineHandler));
            }
            
            if (topicCredentials.CsiId <= 0)
            {
                throw new System.ArgumentException("CsiId parameter of credentials must be positive number");
            }

            string csiId = topicCredentials.CsiId.ToString();
            IUnityCredentials streamCredentials = topicCredentials.GetStreamCredentials();
            IUnityCredentials fallbackCredentials = topicCredentials.GetFallbackCredentials();

            return MakeUnityClient(csiId, credentials, null, offlineHandler, GetUnityProducer(streamCredentials),
                GetUnityProducer(fallbackCredentials));
        }

        static ConsoleUnityClient MakeUnityClient(string csiId, IUnityCredentials credentials, string bufferFilepath, IOfflineHandler offlineHandler,
            IUnityProducer producer, IUnityProducer resourceProducer)
        {
            if (!string.IsNullOrWhiteSpace(bufferFilepath))
            {
            }

            IUnityBuffer mainBuffer;
            IUnityBuffer offlineBuffer = null;
            IAtomicBuffer mainByteBuffer = CreateMainBuffer();

            string offlineBufferFile = null;
            mainBuffer = new UnityRingBuffer(producer, offlineBuffer, mainByteBuffer);

            ConsoleUnityClient client = new ConsoleUnityClient(csiId, credentials, mainBuffer, offlineBuffer, offlineBufferFile, resourceProducer);

            return client;
        }

        private static IAtomicBuffer CreateMainBuffer()
        {
            return new UnsafeBuffer(new byte[1024 * 16 + RingBufferDescriptor.TrailerLength]);
        }
    }
}